package com.demo.crm.springboot3security.security;

import com.demo.crm.springboot3security.entity.Permission;
import com.demo.crm.springboot3security.mapper.PermissionMapper;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
@RequiredArgsConstructor
public class CustomSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private final PermissionMapper permissionMapper;
    private final Map<String, Collection<ConfigAttribute>> configAttributeMap = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        loadResourceDefine();
    }

    private void loadResourceDefine() {
        configAttributeMap.clear();
        List<Permission> permissions = permissionMapper.selectAll();
        
        for (Permission permission : permissions) {
            String key = permission.getUrl() + ":" + permission.getMethod();
            Collection<ConfigAttribute> attrs = configAttributeMap.computeIfAbsent(key, k -> new ArrayList<>());
            attrs.add(new SecurityConfig(permission.getName()));
        }
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        FilterInvocation fi = (FilterInvocation) object;
        HttpServletRequest request = fi.getRequest();
        
        for (Map.Entry<String, Collection<ConfigAttribute>> entry : configAttributeMap.entrySet()) {
            String[] parts = entry.getKey().split(":");
            String url = parts[0];
            String method = parts[1];
            
            AntPathRequestMatcher matcher = new AntPathRequestMatcher(url, method);
            if (matcher.matches(request)) {
                return entry.getValue();
            }
        }
        
        // 如果没有匹配到权限，返回一个特殊的标记
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        Set<ConfigAttribute> allAttributes = new HashSet<>();
        configAttributeMap.values().forEach(allAttributes::addAll);
        return allAttributes;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
} 